package atalskitdb;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.collections.Predicate;

import junit.framework.Assert;

import edu.uci.ics.jung.algorithms.cluster.ClusterSet;
import edu.uci.ics.jung.algorithms.cluster.EdgeBetweennessClusterer;
import edu.uci.ics.jung.algorithms.cluster.WeakComponentClusterer;
import edu.uci.ics.jung.algorithms.connectivity.BFSDistanceLabeler;
import edu.uci.ics.jung.algorithms.connectivity.KNeighborhoodExtractor;
import edu.uci.ics.jung.algorithms.flows.EdmondsKarpMaxFlow;
import edu.uci.ics.jung.algorithms.importance.BetweennessCentrality;
import edu.uci.ics.jung.algorithms.importance.DegreeDistributionRanker;
import edu.uci.ics.jung.algorithms.importance.NodeRanking;
import edu.uci.ics.jung.algorithms.importance.PageRank;
import edu.uci.ics.jung.algorithms.transformation.DirectionTransformer;
import edu.uci.ics.jung.graph.DirectedEdge;
import edu.uci.ics.jung.graph.DirectedGraph;
import edu.uci.ics.jung.graph.Edge;
import edu.uci.ics.jung.graph.Graph;
import edu.uci.ics.jung.graph.Vertex;
import edu.uci.ics.jung.graph.filters.Filter;
import edu.uci.ics.jung.graph.filters.GeneralVertexAcceptFilter;
import edu.uci.ics.jung.graph.impl.DirectedSparseEdge;
import edu.uci.ics.jung.graph.impl.DirectedSparseGraph;
import edu.uci.ics.jung.graph.impl.DirectedSparseVertex;
import edu.uci.ics.jung.graph.impl.SparseGraph;
import edu.uci.ics.jung.graph.impl.SparseVertex;
import edu.uci.ics.jung.graph.impl.UndirectedSparseEdge;
import edu.uci.ics.jung.io.GraphMLFile;
import edu.uci.ics.jung.io.PajekNetWriter;
import edu.uci.ics.jung.utils.GraphUtils;
import edu.uci.ics.jung.utils.MutableDouble;
import edu.uci.ics.jung.utils.UserData;
import graph.SimpleGraphDraw;

public class MainMain {
	public static void main(String[] args) throws Exception {
		/*Map<Integer, User> persons = new HashMap<Integer, User>();
		
		
		Class.forName("com.mysql.jdbc.Driver");
		Connection con = DriverManager.getConnection("jdbc:mysql://localhost/test","root","");
		
		ResultSet rs = con.createStatement().executeQuery("SELECT user_id, authen_login FROM authensrv_userhead");
		
		while(rs.next()) {
			persons.put(rs.getInt(1), new User(rs.getInt(1),rs.getString(2)));
		}
		rs.close();
		
		for(User u : persons.values()) {
			rs = con.createStatement().executeQuery("SELECT member_id FROM blog_circle WHERE status='applied' AND user_id="+u.id);
			while(rs.next()) {
				u.users.add(persons.get(rs.getInt(1)));
			}
		}
		rs.close();
		
		/////////////////////////////
		//build graph
		DirectedGraph g = new DirectedSparseGraph();
		final String name_key = "NAME";
		
		Map<Integer, Vertex> personVertex = new HashMap<Integer, Vertex>();
		for(User u : persons.values()) {
			Vertex uVert =  g.addVertex(new DirectedSparseVertex());
			uVert.addUserDatum(name_key, u.name, UserData.SHARED);
			uVert.addUserDatum(PageRank.KEY, new MutableDouble(1), UserData.SHARED);
			//System.out.println(uVert.getUserDatum(DegreeDistributionRanker.KEY));
			personVertex.put(u.id, uVert);
		}
		
		int i=0;
		userLoop : for(User u : persons.values()) {
			i++;
			for(User member : u.users) {
				Assert.assertNotNull(personVertex.get(u.id));
				Assert.assertNotNull(personVertex.get(member.id));
				Edge e = new  DirectedSparseEdge(personVertex.get(u.id), personVertex.get(member.id));
				for(Predicate p : (Collection<Predicate>)g.getEdgeConstraints()) {
					if(!p.evaluate(e)) {
						continue userLoop;
					}
				}
				g.addEdge(e);
			}
		}
		Filter f = new GeneralVertexAcceptFilter() {

			@Override
			public boolean acceptVertex(Vertex vert) {
				// TODO Auto-generated method stub
				return vert.getInEdges().size()+vert.getOutEdges().size() != 0;
			}

			public String getName() {
				return "ret";
			}
			
		};
		Graph linkedG = f.filter(g).assemble();
		*/
		GraphMLFile writer = new GraphMLFile();
		DirectedGraph linkedG = DirectionTransformer.toDirected(writer.load("graph.xml"));
		
		PageRank centr = new PageRank((DirectedGraph)linkedG, 0.2);
		centr.evaluate();
		//centr.printRankings(true, true);
//		for(NodeRanking rank:(List<NodeRanking>) centr.getRankings()) {
//			System.out.println(String.format("name=%s, rank=%s", rank.vertex.getUserDatum("NAME"), rank.rankScore));
//		}
		/*int delete = (linkedG.numEdges() * 50)/100;
		System.out.println("deleted " +delete);
		EdgeBetweennessClusterer  cluster = new EdgeBetweennessClusterer(delete);
		ClusterSet clSet =  cluster.extract(linkedG);
		System.out.println(clSet.size());
		for(int i =0; i<clSet.size(); ++i) {
			Collection<Vertex> col = (Collection<Vertex>)clSet.getCluster(i);
			System.out.println("cl size="+col.size());
		}*/
		EdmondsKarpMaxFlow neig = new EdmondsKarpMaxFlow(linkedG);
		Vertex user = (Vertex)linkedG.getVertices().iterator().next();
		System.out.println("find for user = " + user.getUserDatum("NAME"));
		neig.labelDistances(linkedG, user);
		for(Vertex v : (Set<Vertex>)linkedG.getVertices()) {
			System.out.println("v "+v.getUserDatum("NAME"));
			System.out.println("dist="+neig.getDistance(linkedG, v));
		}
//		
//		for(Vertex v :(Collection<Vertex>)clSet.getCluster(0)) {
//			System.out.println(v.getUserDatum("NAME"));
//		}
		
		//((NodeRanking)centr.getRankings().get(0)).
		//System.out.println(((Vertex)linkedG.getVertices().iterator().next()).getUserDatum(PageRank.KEY));
	//	writer.save(linkedG, "graph.xml");
		//SimpleGraphDraw.storeJPEG();
	}
	
	static class User {
		int id;
		String name;
		
		List<User> users = new ArrayList<User>();

		public User(int id, String name) {
			super();
			this.id = id;
			this.name = name;
		}
	}
}
